<template>
    <div class="containers" v-loading="loading">
        <div class="canvas" ref="canvas"></div>
        <panel v-if="bpmnModeler" @gridsChange="gridsChange" @getSaveName="getSaveName" :modeler="bpmnModeler" />
        <div class="toolbar">
            <a class="el-button link" ref="withdraw" href="javascript:" @click="handlerUndo" title="撤销操作">撤销</a>
            <a class="el-button link" ref="recover" href="javascript:" @click="handlerRedo" title="恢复操作">恢复</a>
            <a class="el-button link" ref="recover" href="javascript:" @click="handlerZoom(0.1)">放大</a>
            <a class="el-button link" ref="recover" href="javascript:" @click="handlerZoom(-0.1)">缩小</a>
            <a class="el-button link" ref="recover" href="javascript:" @click="handlerZoom(0)">还原</a>
            <a @click="downloadFile('bpmn')" class="el-button link" href="javascript:" ref="saveDiagram" title="保存为BPMN文件">保存为BPMN文件</a>
            <a @click="downloadFile('svg')" class="el-button link" href="javascript:" ref="saveSvg" title="保存为SVG图片">保存为SVG图片</a>
            <a class="el-button link" href="javascript:" title="加载本地BPMN文件">加载本地BPMN文件 <input @change="uploadFile" class="bpmn-file" type="file"></a>
        </div>
    </div>
</template>

<script>
  import BpmnModeler from "bpmn-js/lib/Modeler"; // bpmn-js 设计器
  import panel from "./PropertyPanel"; // 属性面板
  import BpmData from "./BpmData";
  import bpmnXmlStr from "./xmlStr";
  import customTranslate from "./customTranslate/customTranslate";

  export default {
    data() {
      return {
        bpmnModeler: null,
        element: null,
        bpmData: new BpmData(),
        svgName:'diagram.svg',
        bpmnName:'diagram.bpmn',
        loading: false,
        scale:1
      };
    },
    components: {
      panel
    },
    methods: {
      createNewDiagram(xml = bpmnXmlStr) {
        // 将字符串转换成图显示出来
        this.bpmnModeler.importXML(xml, err => {
          if (err) {
            console.error(err);
          } else {
            this.adjustPalette();
          }
          this.loading = false;
        });
      },
      // 调整左侧工具栏排版
      adjustPalette() {
        try {
          // 获取 bpmn 设计器实例
          const canvas = this.$refs.canvas;
          const djsPalette = canvas.children[0].children[1].children[4];
          const djsPalStyle = {
            width: "130px",
            padding: "5px",
            background: "#fff",
            left: "20px",
            borderRadius: 0
          };
          for (let key in djsPalStyle) {
            djsPalette.style[key] = djsPalStyle[key];
          }
          const palette = djsPalette.children[0];
          const allGroups = palette.children;
          allGroups[0].style["display"] = "none";
          console.log(allGroups)
          // 修改控件样式
          for (let gKey in allGroups) {
            const group = allGroups[gKey];
            for (let cKey in group.children) {
              const control = group.children[cKey];
              const controlStyle = {
                display: "flex",
                justifyContent: "flex-start",
                alignItems: "center",
                width: "100%",
                padding: "5px"
              };
              if (
                control.className &&
                control.dataset &&
                control.className.indexOf("entry") !== -1
              ) {
                const controlProps = this.bpmData.getControl(
                  control.dataset.action
                );
                control.innerHTML = `<div style='font-size: 14px;font-weight:500;margin-left:15px;'>${
                  controlProps["title"]
                }</div>`;
                for (let csKey in controlStyle) {
                  control.style[csKey] = controlStyle[csKey];
                }
              }
            }
          }
        } catch (e) {
          console.log(e);
        }
      },
      // 下载为SVG格式,done是个函数，调用的时候传入的
      saveSVG(done) {
        // 把传入的done再传给bpmn原型的saveSVG函数调用
        this.bpmnModeler.saveSVG(done);
      },
      // 下载为SVG格式,done是个函数，调用的时候传入的
      saveDiagram(done) {
        // 把传入的done再传给bpmn原型的saveXML函数调用
        this.bpmnModeler.saveXML({format: true}, function (err, xml) {
          done(err, xml);
        });
      },
      // 当图发生改变的时候会调用这个函数，这个data就是图的xml
      setEncoded(link, name, data) {
        // 把xml转换为URI，下载要用到的
        const encodedData = encodeURIComponent(data);
        // 获取到图的xml，保存就是把这个xml提交给后台
        this.xmlStr = data;
        // 下载图的具体操作,改变a的属性，className令a标签可点击，href令能下载，download是下载的文件的名字
        if (data) {
          link.className = "active el-button link";
          link.href = "data:application/bpmn20-xml;charset=UTF-8," + encodedData;
          link.download = name;
        }
      },
      // 恢复操作
      handlerRedo() {
        this.bpmnModeler.get("commandStack").redo();
      },
      // 撤销操作
      handlerUndo() {
        this.bpmnModeler.get("commandStack").undo();
      },
      // 设置网格背景
      gridsChange(res){
        console.log(res);
        const dom = document.querySelector('.containers');
        dom.className = res ? 'containers grids' : 'containers';
      },
      // 获取设置的svg or bpmn名称
      getSaveName(res){
        console.log(res)
        this[res.key] = res.key === 'svgName' ? `${res.val}.svg` : `${res.val}.bpmn`;
      },
      // 下载文件
      downloadFile(type){
        const _this = this;
        // 获取a标签dom节点
        const downloadSvgLink = this.$refs.saveSvg;
        const downloadLink = this.$refs.saveDiagram;
        // 下载svg
        if(type === 'svg'){
          _this.saveSVG(function (err, svg) {
            console.log(err)
            _this.setEncoded(downloadSvgLink, _this.svgName, err ? null : svg);
          });
        }else{
          // 下载bpmn
          _this.saveDiagram(function (err, xml) {
            console.log(err)
            _this.setEncoded(downloadLink, _this.bpmnName, err ? null : xml);
          });
        }
      },
      // 上传bpmn文件
      uploadFile(event){
        const _this = this;
        _this.loading = true;
        const file = event.target.files[0];
        try {
          const reader = new FileReader();
          reader.readAsText(file);
          if(file){
            reader.onload = function() {
              const result = this.result;
              _this.createNewDiagram(result);
            };
          }
        }catch (e) {
          _this.loading = false;
        }
      },
      // 缩小、放大、还原
      handlerZoom(radio) {
        const newScale = !radio ? 1.0 : this.scale + radio;
        this.bpmnModeler.get("canvas").zoom(newScale);
        this.scale = newScale;
      }
    },
    mounted() {
      const canvas = this.$refs.canvas;
      // 汉化
      const customTranslateModule = {
        translate: ['value', customTranslate]
      };
      // 生成实例
      this.bpmnModeler = new BpmnModeler({
        container: canvas,
        additionalModules: [
          // 汉化
          customTranslateModule
        ]
      });

      // 监听流程图改变事件
      this.bpmnModeler.on("commandStack.changed", function () {

      });

      // 新增流程定义
      this.createNewDiagram();
    }
  };
</script>

<style lang="scss">
    /*左边工具栏以及编辑节点的样式*/
    @import "~bpmn-js/dist/assets/diagram-js.css";
    @import "~bpmn-js/dist/assets/bpmn-font/css/bpmn.css";
    @import "~bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css";
    @import "~bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css";

    .containers {
        position: absolute;
        background-color: #ffffff;
        width: 100%;
        height: 100%;

        .canvas {
            width: 100%;
            height: 100%;
        }

        .panel {
            position: absolute;
            right: 0;
            top: 50px;
            width: 300px;
        }

        .bjs-powered-by {
            display: none;
        }

        .toolbar {
            position: absolute;
            top: 20px;
            right: 350px;

            a {
                text-decoration: none;
                margin: 5px;
                color: #409eff;
            }
        }
    }
    // 网格背景
    .grids {
        background-image: linear-gradient(
                        90deg,
                        rgba(220, 220, 220, 0.5) 6%,
                        transparent 0
        ),
        linear-gradient(rgba(192, 192, 192, 0.5) 6%, transparent 0);
        background-size: 12px 12px;
        width: 100%;
        -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
    }
  .el-button.link{
    font-size: 12px;
    padding:10px;
    position: relative;
  }
  .bpmn-file{
    position: absolute;
    left:0;
    top:0;
    width:100%;
    height:100%;
    opacity: 0;
    z-index: 1;
    cursor: pointer;
  }
</style>
